<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=s, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script>
</head>

<body>
    <div>
        单文件
        <input type="file" id="fileInputCommon">

        <button id="uploadBtnCommon">上传</button>
    </div>



    <div style="margin-top: 500px;">
        切片
        <input type="file" id="fileInput">
        <a id="showProgress" style="display:none;" href="#"></a>
        <button id="uploadBtn">上传</button>

    </div>

    <div style="margin-top: 500px;">

        <a  href="http://localhost:3000/static/index.jpg" download>下载txt</a>
        <button id="download">直接下载</button>
        <button id="downloadDisk">下载磁盘</button>
    </div>
</body>



<script>


    // window.open("http://localhost:3000/static/index.jpg")
    // 下载之二：blob转化
    async function download(param) {
        try {
            // 我们使用axios设置接口返回类型 responseType: "blob", 所以这里从后端返回的是blob。
            console.log(param, "url")
            const res = await fetch(param)
            const blob = await res.blob()
            //把url指向blob 
            // 静态方法会创建一个 DOMString，其中包含一个表示参数中给出的对象的URL。
            // 这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
            let url = URL.createObjectURL(blob)
            const alink = document.createElement('a');
            // url.split('/').pop();
            alink.href = url
            alink.download = new Date().getTime() + ".jpg"
            alink.style.display = "none";
            alink.click();
            alink.remove()
            //解绑
            URL.revokeObjectURL(url)
        } catch (e) {
            console.error(e)
        }
    }
    document.querySelector('#download').addEventListener(('click'), () => {
        download("http://localhost:3000/static/index.jpg")

    })
</script>
<script>
    // 下载之二：blob url 
    async function downloadProgress(response) {
        const reader = response.body.getReader();

        // Step 2：获得总长度（length）
        const contentLength = +response.headers.get('Content-Length');

        // Step 3：读取数据
        let receivedLength = 0; // 当前接收到了这么多字节
        let chunks = []; // 接收到的二进制块的数组（包括 body）
        while (true) {
            const { done, value } = await reader.read();

            if (done) {
                break;
            }

            chunks.push(value);
            receivedLength += value.length;

            console.log(`Received ${receivedLength} of ${contentLength}`)
        }


        // alert("下载完成");

    }


    async function downloadBig(param) {
        try {
            // 我们使用axios设置接口返回类型 responseType: "blob", 所以这里从后端返回的是blob。
            console.log(param, "url")
            // const res = await fetch("http://localhost:3000/static/files/t01b6ccc26385b75557.jpg")
            const res = await fetch(param, {
                method: 'GET',
                // responseType: "arraybuffer",
                // responseType: "blob",
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json',
                },
                // body: JSON.stringify({
                //   firstParam: 'yourValue',
                //   secondParam: 'secondValue',
                // })
            })

            //处理文件（二进制）
            const blob = await res.blob()
            //把url指向blob
            let url = URL.createObjectURL(blob)
            const handle = await window.showSaveFilePicker({
                suggestedName: "hello",
                types: [
                 
                    {
                        description: "jpeg file",
                        accept: {
                            "image/jpeg": [".jpeg"],
                        },
                    },
                    {
                        description: "rar file",
                        accept: {
                            "application/json": [".rar"],
                        },
                    },
                    {
                        description: "text file",
                        accept: {
                            "text/plain": [".txt"],
                        },
                    },
                    {
                        description: "text file",
                        accept: {
                            "text/plain": [".txt"],
                        },
                    },
                ],
            });
            const writable = await handle.createWritable();
            await writable.write(blob);
            
            await writable.close();
            // setTimeout(()=>{
            //     URL.revokeObjectURL(url)
            // },0)
            URL.revokeObjectURL(url)
        } catch (e) {
            console.error(e)
        }
    }
    document.getElementById('downloadDisk').addEventListener('click', () => {
        downloadBig('http://localhost:3000/static/index.jpg')
    })
</script>
<script>



    // 请求基准地址
    axios.defaults.baseURL = 'http://localhost:3000'
    // 选中的文件
    var file = null
    // 选择文件
    document.getElementById('fileInput').onchange = function ({ target: { files } }) {
        file = files[0]
    }

    // 开始上传
    document.getElementById('uploadBtn').onclick = function () {
        if (!file) return;
        // 创建切片   
        // let size = 1024 * 1024 * 10; //10MB 切片大小
        let size = 1024 * 50; //50KB 切片大小
        let fileChunks = [];
        let index = 0 //切片序号
        // step1:这里开始切片
        for (let cur = 0; cur < file.size; cur += size) {
            fileChunks.push({
                hash: index++,
                chunk: file.slice(cur, cur + size)
            })
        }

        // 控制并发和断点续传
        const uploadFileChunks = async function (list) {
            if (list.length === 0) {
                //所有任务完成,合并切片
                await axios({
                    method: 'get',
                    url: '/merge',
                    params: {
                        filename: file.name
                    }
                });
                console.log('上传完成')
                return
            }
            let pool = []//并发池
            let max = 3 //最大并发量
            let finish = 0//完成的数量

            let failList = []//失败的列表
            for (let i = 0; i < list.length; i++) {
                let item = list[i]
                let formData = new FormData()
                formData.append('filename', file.name)
                formData.append('hash', item.hash)
                formData.append('chunk', item.chunk)
                // 上传切片
                let task = axios({
                    method: 'post',
                    url: '/upload',
                    data: formData,
                    // onUploadProgress: function (progressEvent) {
                    //     console.log('进度', progressEvent)
                    // }

                })
                task.then((data) => {
                    // console.log(data, "数据")
                    //请求结束后将该Promise任务从并发池中移除
                    let index = pool.findIndex(t => t === task)
                    pool.splice(index)
                }).catch(() => {
                    failList.push(item)
                }).finally(() => {
                    finish++
                    console.log("进度：" + i / list.length)
                    //所有请求都请求完成
                    if (finish === list.length) {
                        uploadFileChunks(failList)
                    }
                })
                pool.push(task)
                if (pool.length === max) {
                    //每当并发池跑完一个任务，就再塞入一个任务
                    await Promise.race(pool)
                }
            }
        }
        uploadFileChunks(fileChunks)

    }
</script>

</html>

<script>
        // const res = await fetch(param, {
            //     method: 'POST',
            //     // responseType: "arraybuffer",
            //     // responseType: "blob",
            //     headers: {
            //         'Accept': 'application/json',
            //         'Content-Type': 'application/json',
            //     },
            //     // body: JSON.stringify({
            //     //   firstParam: 'yourValue',
            //     //   secondParam: 'secondValue',
            //     // })
            // })
            //处理文件（二进制）
</script>